package com.webapp.org.util.logging;

import org.apache.catalina.tribes.util.Arrays;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect
{
  private Log log = LogFactory.getLog(this.getClass());
  
  @Pointcut("execution(* com.webapp.org.service.*.*(..))")
  protected void loggingOperation(){}
  
  @Before("loggingOperation()")
  @Order(1)
  public void logJoinPoint(JoinPoint joinPoint)
  {System.out.println("before");
	  log.info("Join point kind : " + joinPoint.getKind());  
	  log.info("Signature Declaing type : " + joinPoint.getSignature().getDeclaringTypeName()); 
	  log.info("Signature name : " + joinPoint.getSignature().getName()); 
	  log.info("Arguments : " + Arrays.toString(joinPoint.getArgs())); 
	  log.info("Target Class : " + joinPoint.getTarget().getClass().getName()); 
	  log.info("This Class : " + joinPoint.getThis().getClass().getName()); 
      log.info("Source Location : " + joinPoint.getSourceLocation().toString());
  }
  
  @AfterReturning(pointcut = "loggingOperation()", returning = "result")
  @Order(2)
  public void logAfter(JoinPoint joinPoint, Object result)
  {
	  System.out.println("Afterreturning");
	  log.info("Exiting from Method :"+joinPoint.getSignature().getName());
	  log.info("Return value :"+result);
  }
  
  @AfterThrowing(pointcut = "loggingOperation()", throwing = "e")
  @Order(3)
  public void logAfterThrowing(JoinPoint joinPoint, Throwable e)
  {
	  System.out.println("throwing");
       log.error("An exception has been thrown in "+ joinPoint.getSignature().getName() + "()");
       log.error("Cause :"+e.getCause());
   }
  
  @Around("loggingOperation()")
  @Order(4)
  public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable
  {
	  System.out.println("Around");
   log.info("The method " + joinPoint.getSignature().getName()+ 
		   "() begins with " + Arrays.toString(joinPoint.getArgs()));
     
   try
   {
	   Object result = joinPoint.proceed();
	   log.info("The method " + joinPoint.getSignature().getName()+ "() ends with " + result);
	   return result;
   }
   catch (IllegalArgumentException e)
   {
       log.error("Illegal argument "+ Arrays.toString(joinPoint.getArgs()) + " in "+ joinPoint.getSignature().getName() + "()");
       throw e;
   }        
  }  
}
